package com.service.base_config;

import com.alibaba.fastjson.JSON;
import com.common.baseModel.JsonResult;
import com.common.constant.BaseConst;
import com.common.baseException.CustomizeException;
import com.common.baseException.ExceptionEnum;
import feign.*;
import feign.codec.DecodeException;
import feign.codec.Decoder;
import feign.codec.ErrorDecoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Type;

/**
 * @ClassName FeignConfig
 * @Description TODO
 * @Author 张晓焕
 * @Date 2022/7/15 16:26
 * @Version 1.0
 */
@Slf4j
@Configuration
public class FeignConfig implements RequestInterceptor, ErrorDecoder , Decoder {
    @Value("${sa-token.token-name}")
    String tokenName;
    public FeignConfig(){

    }
    public FeignConfig(String tokenName) {
        this.tokenName = tokenName;
    }

    public String getTokenName() {
        return tokenName;
    }

    public void setTokenName(String tokenName) {
        this.tokenName = tokenName;
    }


    @Override
    public void apply(RequestTemplate requestTemplate) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        //添加token
        requestTemplate.header(tokenName, request.getHeader(tokenName));
    }

    /**
     * 请求异常解析
     * 这是因为在OpenFeign中，如果发生错误时，会抛出FeignException异常，
     * 而默认的ErrorDecoder实现只会将响应信息封装到FeignException异常中。
     * 如果我们想要自定义异常，并将响应信息封装到自定义的异常中，就需要实现ErrorDecoder接口。
     * @param s
     * @param response
     * @return
     */
    @Override
    public Exception decode(String s, Response response) {
        log.info("fegin调用异常#######{}",s);
        log.info("fegin调用异常Response#######{}",response);
        return new CustomizeException(ExceptionEnum.FEIGN_ERROR);
    }

    /**
     * 请求正向解析 提取对象
     * @param response
     * @param type
     * @return
     * @throws IOException
     * @throws DecodeException
     * @throws FeignException
     */
    @Override
    public Object decode(Response response, Type type) throws IOException, DecodeException, FeignException {

        Reader reader = response.body().asReader(Util.UTF_8);
        String res = Util.toString(reader);
        log.info("调用获取返回结果{}",res);
        JsonResult result = JSON.parseObject(res, JsonResult.class);
        if(result.getCode()== BaseConst.ResCode.SUCCESS){
            throw new CustomizeException(ExceptionEnum.FEIGN_ERROR);
        }else {
            return result.getData();
        }
    }
}
